package com.SmartCare.service.impl;

import com.SmartCare.common.Result;
import com.SmartCare.common.dto.attendance.AttendanceDTO;
import com.SmartCare.common.dto.attendance.AttendanceUserTop;
import com.SmartCare.common.dto.role.ElderlyDTO;
import com.SmartCare.common.enums.Constants;
import com.SmartCare.common.exception.ServiceException;
import com.SmartCare.common.vo.AttendanceVo;
import com.SmartCare.mapper.AttendanceMapper;
import com.SmartCare.mapper.role.ElderlyInformationMapper;
import com.SmartCare.mapper.role.UserMapper;
import com.SmartCare.pojo.Attendance;
import com.SmartCare.pojo.role.ElderlyInformation;
import com.SmartCare.pojo.role.User;
import com.SmartCare.service.AttendanceService;
import com.SmartCare.utils.DateTimeUtils;
import com.SmartCare.utils.ElderTransToDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AttendanceServiceImpl extends ServiceImpl<AttendanceMapper, Attendance> implements AttendanceService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private ElderlyInformationMapper elderlyInformationMapper;

    @Resource
    private ElderTransToDTO elderTransToDTO;

    /**
     * 签到
     */
    @Override
    public Result checkIn(Long visitorId, Long elderId) {
        Attendance attendance = Attendance.builder()
                .visitorId(visitorId)
                .elderId(elderId)
                .checkInTime(LocalDateTime.now())
                .status(1) //已签到但未签退
                .build();
        boolean res = save(attendance);

        if (res) {
            LambdaQueryWrapper<Attendance> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Attendance::getVisitorId, visitorId);
            wrapper.orderByDesc(Attendance::getCheckInTime);
            wrapper.last("LIMIT 1");
            Attendance one = getOne(wrapper);
            if (one != null) {
                return Result.success("签到成功", one.getId());
            }
        }
        return Result.error("签到失败");
    }

    /**
     * 签退
     */
    @Override
    public Result checkOut(Long id) {
        //先查询签到时间
        LambdaQueryWrapper<Attendance> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Attendance::getId, id);
        //计算时长（分钟）
        LocalDateTime checkInTime = getOne(wrapper).getCheckInTime();
        LocalDateTime checkOutTime = LocalDateTime.now();
        Duration duration = Duration.between(checkInTime, checkOutTime);
        Long durationMinutes = duration.toMinutes();
        if (durationMinutes <= 1) {
            return Result.error("一分钟内签退无效");
        }

        //签退处理
        LambdaUpdateWrapper<Attendance> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Attendance::getId, id);
        updateWrapper.set(Attendance::getCheckOutTime, checkOutTime);
        updateWrapper.set(Attendance::getVisitDuration, durationMinutes);
        updateWrapper.set(Attendance::getStatus, 2);//已签到并签退
        boolean res = update(updateWrapper);
        if (res) {
            return Result.success("签退成功");
        }
        return Result.error("签退失败");
    }

    /**
     * 个人访问信息查询
     */
    @Override
    public Result getOneInfo(Long visitorId) {
        LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(6);
        LambdaUpdateWrapper<Attendance> wrapper = new LambdaUpdateWrapper<>();
        wrapper.between(Attendance::getCreateTime, times[0], times[1]);
        wrapper.eq(Attendance::getVisitorId, visitorId);
        wrapper.orderByDesc(Attendance::getCreateTime);
        List<Attendance> list = list(wrapper);
        if (list == null) {
            return Result.error("无记录");
        }
        return Result.success("查询成功", list);
    }

    /**
     * 排行榜查询(未完善)
     */
    @Override
    public Result getTop(Integer flag) {
        QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 2);

        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;

        if (flag == 1) {
            LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(1);
            startDateTime = times[0];
            endDateTime = times[1];
        } else if (flag == 2) {
            LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(6);
            startDateTime = times[0];
            endDateTime = times[1];
        } else if (flag == 3) {
            LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(31);
            startDateTime = times[0];
            endDateTime = times[1];
        } else if (flag == 4) {
            LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(365);
            startDateTime = times[0];
            endDateTime = times[1];
        }

        if (startDateTime != null && endDateTime != null) {
            wrapper.between("create_time", startDateTime, endDateTime);
        }

        List<Map<String, Object>> resultList = listMaps(wrapper
                .select("visitor_id, SUM(visit_duration) as totalDuration")
                .groupBy("visitor_id")
                .orderByDesc("totalDuration"));


        // 构建结果列表
        /* List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> map : resultList) {
            Integer visitorId = (Integer) map.get("visitor_id");
            Long totalDuration = ((BigDecimal) map.get("totalDuration")).longValue();
            // 创建一个新的Map对象，并添加visitorId和totalDuration键值对
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("visitorId", visitorId);
            resultMap.put("totalDuration", totalDuration);
            // 将resultMap添加到结果列表中
            result.add(resultMap);
        } */
        // 返回结果
        return Result.success(resultList);
    }

    @Override
    public Result getAttendanceData(String careHomeName) {
        //获取该养老院的排行榜数据
        QueryWrapper<Attendance> qw = new QueryWrapper<>();

        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.select("user_id, name, nickname, avatar_url");
        userQuery.eq("care_home_name", careHomeName);

        List<User> matchingUsers = userMapper.selectList(userQuery);

        if (matchingUsers.isEmpty()) {
            return Result.success();
        }

//        List<UserTemp> users=new ArrayList<>();
//        matchingUsers.forEach((item)->{
//            UserTemp temp = new UserTemp();
//            BeanUtils.copyProperties(item,temp);
//            users.add(temp);
//        });

        List<Long> userIds = matchingUsers.stream()
                .map(User::getUserId)
                .collect(Collectors.toList());
        qw.eq("status", 2);
        qw.select("Attendance.*");
        qw.in("visitor_id", userIds);
        List<Attendance> attendanceList = list(qw);

        //使用stream将Attendance记录按访问者id分组，并计算duration之和和访问次数
        Map<Long, Map<String, Object>> visitorData = new HashMap<>();
        for (Attendance attendance : attendanceList) {
            Long visitorId = attendance.getVisitorId();
            if (!visitorData.containsKey(visitorId)) {
                visitorData.put(visitorId, new HashMap<>());
            }

            //计算总访问时间
            Long totalDuration = visitorData.get(visitorId).get("totalDuration") != null ?
                    (Long) visitorData.get(visitorId).get("totalDuration") : 0L;
            totalDuration += attendance.getVisitDuration();
            visitorData.get(visitorId).put("totalDuration", totalDuration);

            //计算访问次数
            Long visitCount = visitorData.get(visitorId).get("visitCount") != null ?
                    (Long) visitorData.get(visitorId).get("visitCount") : 0L;
            visitCount += 1L;
            visitorData.get(visitorId).put("visitCount", visitCount);

            //获取对应的User对象并放入visitorData中
            matchingUsers.stream()
                    .filter(u -> u.getUserId().equals(visitorId))
                    .findFirst()
                    .ifPresent(user -> visitorData.get(visitorId).put("user", user));

        }

        //将结果添加到返回的Result中并按totalDuration降序排序
        List<Map.Entry<Long, Map<String, Object>>> result = visitorData.entrySet().stream()
                .sorted(Comparator.comparingLong(entry -> -((Long) entry.getValue().get("totalDuration"))))
                .collect(Collectors.toList());

        return Result.success(result);
    }

    /**
     * 所有签到信息查询
     */
    @Override
    public Result getSignInfo(Long visitorId, Long elderId) {
        LocalDateTime[] times = DateTimeUtils.getStartAndEndDateTime(0);

        LambdaQueryWrapper<Attendance> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Attendance::getVisitorId, visitorId);
        wrapper.eq(Attendance::getStatus, 1);
        wrapper.between(Attendance::getCreateTime, times[0], times[1]);
        Attendance one = getOne(wrapper);
        if (one != null) {
            AttendanceVo vo = new AttendanceVo();
            BeanUtils.copyProperties(one, vo);
            return Result.success(vo);
        }
        return Result.success();
    }

    @Override
    public Result search(String careHomeName, Integer pageNum, Integer pageSize, String keyword, String type) {

        IPage<Attendance> iPage = new Page<>(pageNum, pageSize);
        //获取该养老院的排行榜数据
        QueryWrapper<Attendance> qw = new QueryWrapper<>();
        qw.orderByDesc("check_in_time");

        //区分养老院
        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.select("user_id, name, nickname, avatar_url");
        userQuery.eq("care_home_name", careHomeName);

        //如果是根据用户名搜索
        if (type.equals("visitor_id")) {
            userQuery.like("name", keyword);
        }
        List<User> matchingUsers = userMapper.selectList(userQuery);
        //用户序列判空
        if (matchingUsers.size() == 0) {
            return Result.success(new Page<AttendanceDTO>());
        }
//        List<UserTemp> users=new ArrayList<>();
//        matchingUsers.forEach((item)->{
//            UserTemp temp = new UserTemp();
//            BeanUtils.copyProperties(item,temp);
//            users.add(temp);
//        });

        List<Long> userIds = matchingUsers.stream()
                .map(User::getUserId)
                .collect(Collectors.toList());
        qw.select("Attendance.*");
        qw.in("visitor_id", userIds);

        //如果是根据老人姓名搜索
        if (type.equals("elder_id")) {
            QueryWrapper<ElderlyInformation> elderQuery = new QueryWrapper<>();
            elderQuery.like("elderly_name", keyword);
            List<ElderlyInformation> elderList = elderlyInformationMapper.selectList(elderQuery);
            //老人序列判空
            if (elderList.size() == 0) {
                return Result.success(new Page<AttendanceDTO>());
            }
            List<Long> elderIds = elderList.stream()
                    .map(ElderlyInformation::getElderlyId)
                    .collect(Collectors.toList());
            qw.in("elder_id", elderIds);
        }
        //根据其它字段搜索，直接模糊查询
        if (!type.equals("elder_id") && !type.equals("visitor_id")) {
            qw.like(type, keyword);
        }

        //获取分页查询数据
        IPage<Attendance> page = page(iPage, qw);

        //将records中的数据转成dto
        List<AttendanceDTO> dtos = new ArrayList<>();
        for (Attendance attendance : page.getRecords()) {
            QueryWrapper<User> uqw = new QueryWrapper<>();
            uqw.select("user_id, name, nickname, avatar_url");
            uqw.eq("user_id", attendance.getVisitorId());
            User visitor = userMapper.selectOne(uqw);
            ElderlyInformation elder = elderlyInformationMapper.selectById(attendance.getElderId());
            ElderlyDTO elderDTO = null;
            if (elder != null) {
                elderDTO = elderTransToDTO.trans(elder);
            }
            //添加dto
            dtos.add(AttendanceDTO.builder()
                    .id(attendance.getId())
                    .elderly(elderDTO)
                    .visitor(visitor)
                    .createTime(attendance.getCreateTime())
                    .visitDuration(attendance.getVisitDuration())
                    .checkInTime(attendance.getCheckInTime())
                    .checkOutTime(attendance.getCheckOutTime())
                    .status(attendance.getStatus())
                    .build());
        }
        //将分页数据转成DTO
        IPage<AttendanceDTO> result = new Page<>();
        result.setSize(page.getSize());
        result.setCurrent(page.getCurrent());
        result.setTotal(page.getTotal());
        result.setPages(page.getPages());
        result.setRecords(dtos);

        return Result.success(result);
    }

    @Override
    public Result getWeekAttendance(String careHomeName) {
        //获取该养老院的本周排行榜数据
        QueryWrapper<Attendance> qw = new QueryWrapper<>();
        //限制获取条件
        qw.eq("status", 2);
        //检查签到时间是否在本周内
        qw.apply("YEARWEEK(check_in_time, 1) = YEARWEEK({0}, 1)", LocalDateTime.now());
        //限制用户为本养老院的用户
        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.select("user_id, name, nickname, avatar_url");
        userQuery.eq("care_home_name", careHomeName);

        List<User> matchingUsers = userMapper.selectList(userQuery);

        if (matchingUsers.isEmpty()) {
            return Result.success();
        }
//        List<UserTemp> users=new ArrayList<>();
//        matchingUsers.forEach((item)->{
//            UserTemp temp = new UserTemp();
//            BeanUtils.copyProperties(item,temp);
//            users.add(temp);
//        });

        List<Long> userIds = matchingUsers.stream()
                .map(User::getUserId)
                .collect(Collectors.toList());

        qw.select("Attendance.*");
        qw.in("visitor_id", userIds);
        List<Attendance> attendanceList = list(qw);

        //使用stream将Attendance记录按访问者id分组，并计算duration之和和访问次数
        Map<Long, Map<String, Object>> visitorData = new HashMap<>();
        for (Attendance attendance : attendanceList) {
            Long visitorId = attendance.getVisitorId();
            if (!visitorData.containsKey(visitorId)) {
                visitorData.put(visitorId, new HashMap<>());
            }

            //计算总访问时间
            Long totalDuration = visitorData.get(visitorId).get("totalDuration") != null ?
                    (Long) visitorData.get(visitorId).get("totalDuration") : 0L;
            totalDuration += attendance.getVisitDuration();
            visitorData.get(visitorId).put("totalDuration", totalDuration);

            //计算访问次数
            Long visitCount = visitorData.get(visitorId).get("visitCount") != null ?
                    (Long) visitorData.get(visitorId).get("visitCount") : 0L;
            visitCount += 1L;
            visitorData.get(visitorId).put("visitCount", visitCount);

            //获取对应的User对象并放入visitorData中
            matchingUsers.stream()
                    .filter(u -> u.getUserId().equals(visitorId))
                    .findFirst()
                    .ifPresent(user -> visitorData.get(visitorId).put("user", user));

        }
        //将结果添加到返回的Result中并按totalDuration降序排序
        List<Map.Entry<Long, Map<String, Object>>> result = visitorData.entrySet().stream()
                .sorted(Comparator.comparingLong(entry -> -((Long) entry.getValue().get("totalDuration"))))
                .collect(Collectors.toList());

        return Result.success(result);
    }

    @Override
    public Result topByUser(String careHomeName, String startTime, String endTime) {
        // 先获取本养老院的用户ID列表
        QueryWrapper<User> uqw = new QueryWrapper<>();
        uqw.select("user_id, name, nickname, avatar_url");
        uqw.eq("care_home_name", careHomeName);
        List<User> users = userMapper.selectList(uqw);
        List<Long> ids = users.stream()
                .map(User::getUserId)
                .collect(Collectors.toList());
        // 获取符合条件的到访记录
        QueryWrapper<Attendance> aqw = new QueryWrapper<>();
        aqw.between("create_time", startTime, endTime);
        aqw.in("visitor_id", ids);
        aqw.eq("status", 2);
        List<Attendance> list = list(aqw);

        // 根据用户进行分类，统计每个用户的到访时间
        Map<Long, Long> moduleCallCounts = list.stream()
                .collect(Collectors.groupingBy(Attendance::getVisitorId, Collectors.summingLong(Attendance::getVisitDuration)));
        // 将数据进行排序
        List<AttendanceUserTop> tops = new ArrayList<>();
        for (Long userId : moduleCallCounts.keySet()) {
            // 从上面获取的用户列表里再去过滤，查询指定id的用户
            List<User> fitList = users.stream().filter(user -> user.getUserId().equals(userId)).collect(Collectors.toList());
            if (fitList.size() == 0) {
                continue;
//                throw new ServiceException(Constants.CODE_400, "用户不存在");
            }
            tops.add(AttendanceUserTop.builder()
                    .user(fitList.get(0))
                    .duration(moduleCallCounts.get(userId))
                    .build());
        }
        tops.sort(Comparator.comparing(AttendanceUserTop::getDuration));
        return Result.success(tops);
    }

}
